﻿using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Xsl;
using System.Xml.XPath;
using System.Web;
using System.IO;
using System;
using Saxon.Api;


namespace SBS.Common.Saxon
{
    public class XQuery
    {
        public Uri BaseUri { get; set; }
        public Uri InputUri { get; set; }
        public string InputXmlFile{ get; set; }
        public string InputXmlString { get; set; }
        public XmlNode InputXmlNode { get; set; }
        public Stream InputStream { get; set; }
        public string InputXQFile { get; set; }
        public string InputXQString { get; set; }
        /// <summary>
        /// 指定转换方法，可选值有：xml,html,text。其中 xml 为默认值
        /// </summary>
        public string Method { get; set; }
        public Dictionary<QName, XdmValue> ExternalVariable { get; set; }

        private string GetXmlString()
        {            
            if (!string.IsNullOrEmpty(this.InputXmlString))
            {
                return this.InputXmlString;
            }
            else if (!string.IsNullOrEmpty(this.InputXmlFile))
            {                
                return File.ReadAllText(this.InputXmlFile, Encoding.UTF8);
            }
            return null;
        }
        private string GetXQString()
        {            
            if (!string.IsNullOrEmpty(this.InputXQString))
            {
                return this.InputXQString;
            }
            else if (!string.IsNullOrEmpty(this.InputXQFile))
            {
                string xquery = "";
                StreamReader sr = new StreamReader(this.InputXQFile);
                xquery = sr.ReadToEnd();
                sr.Close();
                return xquery;
            }
            return null;
        }

        public string Execute()
        {                        
            Processor processor = new Processor();
            DocumentBuilder DB = processor.NewDocumentBuilder();
            DB.BaseUri = this.BaseUri==null ? new Uri("http://www.sbsinc.cn") : this.BaseUri;
            XdmNode Doc = null;
            string xmlstr = this.GetXmlString();
            if (!string.IsNullOrEmpty(xmlstr))
            {
                TextReader tr = new StringReader(xmlstr);
                Doc = DB.Build(tr);
                tr.Close();
            }
            else if(this.InputStream!=null)
            {
                Doc = DB.Build(this.InputStream);
            }
            else if (this.InputUri != null)
            {
                Doc = DB.Build(this.InputUri);
            }
            else if (this.InputXmlNode != null)
            {
                Doc = DB.Build(this.InputXmlNode);
            }
            XQueryCompiler compiler = processor.NewXQueryCompiler();
            XQueryExecutable exp = compiler.Compile(this.GetXQString());
            XQueryEvaluator eval = exp.Load();
            eval.ContextItem = Doc;                                   
            
            Serializer qout = new Serializer();            
            if (this.Method != null)
            {                
                qout.SetOutputProperty(Serializer.METHOD, this.Method);
            }
            StringBuilder sb = new StringBuilder();
            using (TextWriter tw = new StringWriter(sb))
            {
                qout.SetOutputWriter(tw);
                if (this.ExternalVariable != null)
                {
                    foreach (QName n in this.ExternalVariable.Keys)
                    {
                        eval.SetExternalVariable(n, this.ExternalVariable[n]);
                    }
                }
                eval.Run(qout);                                
            }            
            qout.Close();
            
           
            return sb.ToString();
        }
    }    

}
